/**
 * 公共函数
 */
export default {
    /**
     *
     * @param {array} menuList 菜单列表
     * @returns {array}
     */
    addRouterAuth(menuList) {
        let menus = [];

        for (let i in menuList) {

            const routerUrl = menuList[i].path + '/index.vue';

            let name = menuList[i].name;
            name = name.charAt(0).toUpperCase() + name.slice(1);
            menus.push({
                path: menuList[i].path,
                menuName: menuList[i].name,
                name: name,
                meta: {
                    auth: []
                },
                component: () => import('@/views' + routerUrl)
            });
        }

        return menus;
    },
    /**
     * Canvas画图
     * @param {*} data 传的参数{id,text}
     */
    initCanvas(data) {
        var canvas = document.getElementById(data.id);
        var ctx = canvas.getContext('2d');

        canvas.width = data.width || 300;
        canvas.height = data.height || 45;

        canvas.style.letterSpacing = 4 + 'px';
        ctx.font = 'bold 18px SourceHanSansSC';

        var gradient = ctx.createLinearGradient(0, 0, canvas.width + 100, 0);
        gradient.addColorStop('0', '#1a64c3');
        gradient.addColorStop('0.5', '#693a9d');
        gradient.addColorStop('1.0', '#9e302b');
        ctx.strokeStyle = gradient;
        ctx.lineWidth = 4;
        this.fillText(ctx, data.text);
    },
    /**
     * Canvas画图添加文本
     * @param {*} ctx Canvas
     * @param {*} text 文本
     */
    fillText(ctx, text) {
        ctx.clearRect(0, 0, 300, 200);
        ctx.strokeText(text, 10, 30);
        ctx.fillStyle = 'white';
        ctx.fillText(text, 10, 30);
    },
    /**
     * 根据起点和终点获取方向：1：向上，2：向下，3：向左，4：向右，0：未滑动
     * @param {Number} startX 开始的X值
     * @param {Number} startY 开始的Y值
     * @param {Number} endX 结束的X值
     * @param {Number} endY 结束的Y值
     * @returns 
     */
    getSlideDirection(startX, startY, endX, endY) {
        var dy = startY - endY;
        var dx = endX - startX;
        var result = 0;
        //如果滑动距离太短
        if (Math.abs(dx) < 2 && Math.abs(dy) < 2) {
            return result;
        }
        var angle = this.getSlideAngle(dx, dy);
        if (angle >= -45 && angle < 45) {
            result = 4;
        } else if (angle >= 45 && angle < 135) {
            result = 1;
        } else if (angle >= -135 && angle < -45) {
            result = 2;
        } else if ((angle >= 135 && angle <= 180) || (angle >= -180 && angle < -135)) {
            result = 3;
        }
        return result;
    },
    /**
     * 计算角度
     */
    getSlideAngle(dx, dy) {
        return Math.atan2(dy, dx) * 180 / Math.PI;
    },
    /**
     * 滑动动画
     * @param {Number} begin 开始偏移量
     * @param {Number} end 结束偏移量
     * @param {Number}  持续时间 
     * @param {Function} changeCallback 滑动时回调
     * @param {Function} finishCallback 结束时回调
     */
    animateTo(begin, end, duration, changeCallback, finishCallback) {
        // 动画开始时间
        let startTime = Date.now();
        let that = this;
        requestAnimationFrame(function update() {
            // 当前执行的时间
            let dataNow = Date.now();
            // 当前所消耗的时间
            let time = dataNow - startTime;
            // 当前发生的位移
            let value = that.linear(time, begin, end, duration);
            // 执行变化事件回调
            typeof changeCallback === 'function' && changeCallback(value);
            // 如果动画结束时间大于当前执行时间
            if (startTime + duration > dataNow) {
                // 在执行一次动画渲染
                requestAnimationFrame(update);
            } else {
                // 执行结束回调
                typeof finishCallback === 'function' && finishCallback(end);
            }
        });
    },
    /**
     * 
     * @param {Number} time 当前时间
     * @param {Number} begin 开始位移
     * @param {Number} end 结束时间
     * @param {Number} duration 当前位移
     * @returns 
     */
    linear(time, begin, end, duration) {
        return (end - begin) * time / duration + begin;
    },
    /**
     * 随机整数
     * @param {Number} min 最小数
     * @param {Number} max 最大数
     * @returns {Number}
     */
    randomInteger(min, max) {
        let range = max - min;
        let rand = Math.random();
        return min + Math.round(rand * range);
    },
    /**
     * 随机小数(保留一位小数)
     * @returns {Number}
     */
    RandomDecimal(min, max) {
        let range = max - min;
        let rand = Math.random();
        return min + Math.round(range * rand * 10) / 10;
    },
    /**
     * 瀑布流
     * @param {*} vm this
     * @param {*} parent 瀑布流组件
     * @param {*} arg { margin：父元素margin，vgap：块之间水平间隙，hgap：块之间竖立间隙，cols：设置列数 }
     */
    waterFall(vm, parent, arg) {
        vm.$nextTick(() => {

            setTimeout(() => {
                // 没有子元素停止继续执行,防止报错
                if (parent == null || parent.children.length <= 0) {
                    console.warn('没有子元素');
                    return;
                }

                let margin = arg.margin || 0;
                let divVgap = arg.vgap || 20;
                let divHgap = arg.hgap || 20;
                let screenWidth = parent.clientWidth; // 父元素宽
                let childrenWidth = parent.children[0].clientWidth; // 子元素宽
                if (childrenWidth < 400) childrenWidth = 400;

                // 1、未设置子元素宽前需给定子元素最大宽，并按容器比例算出列数
                let boxWidth = childrenWidth > 400 ? 400 : childrenWidth;
                let num = Math.round(screenWidth / boxWidth);
                if (num < 1) num = 1;
                let columns = num;

                // 2、计算父容器宽（容器总宽 - (间隙 * 列数) + 外边框距离）最后要在上一层设置padding（需与这里的margin像素一致）
                // 确定子元素宽度
                // 并通过所有子元素创建一个数组
                let pageWidth = screenWidth - divVgap * columns + margin;
                let itemWidth = parseInt(pageWidth / columns);
                let list = Array.from(parent.children);

                let arr = [];

                list.forEach((item, index) => {
                    // 3、所有子元素设置宽,并获取所有元素的高
                    item.style.width = itemWidth + 'px';
                    let height = item.clientHeight || item.offsetHeight;

                    if (index < columns) {
                        // 4、设置第一行布局
                        item.setAttribute('style', `top:0;left:${(itemWidth) * index + divVgap * index}px;width:${itemWidth}px`);
                        arr.push(height); // 行高push到数组
                    } else {
                        // 5、其他行，找到数组中最小高度和它的索引
                        let minHeight = arr[0];
                        let i = 0;
                        for (let j = 0; j < arr.length; j++) {
                            if (minHeight > arr[j]) {
                                minHeight = arr[j];
                                i = j;
                            }
                        }

                        // 6、设置下一行的第一个盒子位置；top值就是最小列高度
                        item.setAttribute('style', `top:${arr[i] + divHgap}px;left:${(itemWidth) * i + divVgap * i}px;width:${itemWidth}px`);

                        // 7、最小列的高度
                        // 最小列的高度 = 当前自己的高度 + 拼接的高度 + 竖直间隔
                        arr[i] = arr[i] + height + divHgap;
                    }
                });

                // 取最高值
                let max = Math.max.apply(null, arr);

                parent.setAttribute('style', `height:${max}px`);

            }, 100);
        });
    },

    /**
     * 查找父级
     * @param {Object} child 当前dom
     * @param {String} parentName 查找的父className
     * @returns {Boolean}
     */
    findParents(child, parentName) {
        if (typeof child.parentNode.className === 'undefined') return true;

        if (child.parentNode.className.indexOf(parentName) > -1) {
            return false;
        } else {
            return this.findParents(child.parentNode, parentName);
        }
    },

    /**
     * 滚动节流
     * @param {Function} fun 函数
     * @param {Number} wait 
     * @param {Number} mustRun 等待时间
     * @returns 
     */
    scrollThrottle(fun, wait, mustRun) {
        let timeout, startTime = new Date();
        return function () {
            let context = this,
                args = arguments,
                curTime = new Date(),
                scrollTop = document.documentElement.scrollTop || document.body.scrollTop,
                clientHeight = document.documentElement.clientHeight || document.body.clientHeight,
                scrollHeight = document.documentElement.scrollHeight || document.body.scrollHeight;

            // 判断是否滚动到底部
            if (scrollTop + clientHeight === scrollHeight) {
                clearTimeout(timeout);
                // 如果达到了规定的触发时间间隔，触发fun函数
                if (curTime - startTime >= mustRun) {
                    fun.apply(context, args);
                    startTime = curTime;
                } else { // 没有达到触发间隔，重新设定计算器
                    timeout = setTimeout(fun, wait);
                }
            }

        };
    }
};
